package com.smartfast4j.backend.modules.sys.security.shiro;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.smartfast4j.backend.common.util.CacheUtil;
import com.smartfast4j.backend.modules.sys.entity.SysUser;
import com.smartfast4j.backend.modules.sys.service.SysMenuService;
import com.smartfast4j.backend.modules.sys.service.SysUserService;
import com.smartfast4j.backend.modules.sys.vo.SysMenuVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * 系统用户认证
 * Created by gacl on 2017/3/3.
 */
public class SysUserRealm2 extends AuthorizingRealm {

    protected Logger logger = Logger.getLogger(getClass());

    /**
     * 用户权限缓存Key
     */
    private String authorizationinfo_keyprefix = "shiro_redis_authorizationInfo:";

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 获取登录用户的授权信息
     * @param principalCollection
     * @return
     */
    private SimpleAuthorizationInfo getLoginUserAuthorizationInfo(PrincipalCollection principalCollection){
        SysUser user = (SysUser)principalCollection.getPrimaryPrincipal();
        Long userId = user.getUserId();
        //用户权限列表
        List<String> permsList = null;
        //从缓存中读取用户权限缓存信息
        String permsListCacheStr = CacheUtil.getString(authorizationinfo_keyprefix+userId);
        logger.debug("从缓存中读取用户权限缓存信息，permsListCacheStr="+permsListCacheStr);
        if(StringUtils.isNotEmpty(permsListCacheStr)){
            permsList = JSON.parseArray(permsListCacheStr,String.class);
        }else{
            //系统管理员，拥有最高权限
            if(userId == 1){
                List<SysMenuVo> menuList = sysMenuService.queryAllMenuList();
                permsList = new ArrayList<>(menuList.size());
                for(SysMenuVo menu : menuList){
                    permsList.add(menu.getPerms());
                }
            }else{
                //根据用户ID查询用户权限
                permsList = sysUserService.queryAllPerms(userId);
            }
            //缓存用户权限集合
            CacheUtil.setString(authorizationinfo_keyprefix+userId, JSON.toJSONString(permsList));
        }

        //用户权限列表
        Set<String> permsSet = new HashSet<>();
        for(String perms : permsList){
            if(StringUtils.isBlank(perms)){
                continue;
            }
            permsSet.addAll(Arrays.asList(perms.trim().split(",")));
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }

    /**
     * 授权(验证权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        logger.info("调用doGetAuthorizationInfo验证用户权限");
        return getLoginUserAuthorizationInfo(principalCollection);
    }

    /**
     * 认证(登录时调用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        logger.info("调用doGetAuthenticationInfo进行用户登录");
        /**
         * 获取用户输入的登录用户名
         */
        String userName = (String) authenticationToken.getPrincipal();
        /**
         * 获取用户输入的登录密码
         */
        String password = new String((char[]) authenticationToken.getCredentials());

        //根据用户名查询用户信息
        SysUser searchCondition = new SysUser();
        searchCondition.setUsername(userName);
        EntityWrapper<SysUser> sysUserEntityWrapper = new EntityWrapper<>(searchCondition);
        SysUser sysUser = sysUserService.selectOne(sysUserEntityWrapper);
        //用户不存在
        if(sysUser == null){
            throw new UnknownAccountException("账号或密码不正确");
        }
        //密码错误
        if(!password.equals(sysUser.getPassword())) {
            throw new IncorrectCredentialsException("账号或密码不正确");
        }
        //账号锁定（'状态  0：禁用   1：正常'）
        if(sysUser.getStatus() == 0){
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        return new SimpleAuthenticationInfo(sysUser, password, getName());
    }
}
